const readline = require('readline')
const fs = require('fs')
const path = require('path')

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
})

const scan = tips => {
  return new Promise((resolve, rejects) => {
    rl.question(tips, function (answer) {
      resolve(answer)
      rl.close()
    })
  })
}

function getTemplate(
  compName,
  hyphenCompName,
  underlineCompName,
  smallHumpCompName
) {
  const indexTemplate = [
    `import ${compName} from './${hyphenCompName}'`,
    `export default ${compName}`,
    '',
    `export * from './config'`,
    `export * from './${hyphenCompName}'`,
  ]

  const compTemplate = [
    "import React, { FC } from 'react'",
    `import { ${compName}Props, DISPLAY_NAME_${underlineCompName.toUpperCase()}, get${compName}ClassNames } from './config'`,
    '',
    `export const ${compName}: FC<${compName}Props> = props => {`,
    '',
    `  const ${smallHumpCompName}Classes = get${compName}ClassNames(props)`,
    '',
    '  return <></>',
    '}',
    `${compName}.displayName = DISPLAY_NAME_${underlineCompName.toUpperCase()}`,
    '',
    `export default ${compName}`,
  ]

  const configTemplate = [
    "import classNames from 'classnames'",
    '',
    `export const DISPLAY_NAME_${underlineCompName.toUpperCase()} = '${compName}'`,
    '',
    `export interface ${compName}Props {}`,
    '',
    '// 获取组件配置的class',
    `export const get${compName}ClassNames = (props: ${compName}Props, extendClass?: () => Object) => {`,
    '  return classNames(',
    `    '${hyphenCompName}',`,
    '    extendClass && extendClass()',
    '  )',
    `}`,
  ]

  const storyTemplate = [
    "import React from 'react'",
    "import { storiesOf } from '@storybook/react'",
    "import { action } from '@storybook/addon-actions'",
    `import ${compName} from './index'`,
    '',
    `storiesOf('${compName} Component', module)`,
  ]

  return {
    indexTemplate: indexTemplate.join('\n'),
    compTemplate: compTemplate.join('\n'),
    configTemplate: configTemplate.join('\n'),
    storyTemplate: storyTemplate.join('\n'),
  }
}

function buildDir(compName) {
  return new Promise((resolve, rejects) => {
    const compPath = path.resolve(__dirname, `../src/components/${compName}`)
    const stylePath = path.resolve(__dirname, `../src/styles`)

    const hyphenCompName = compName
      .replace(/(?!^)([A-Z])/g, '-$1')
      .toLowerCase()
    const underlineCompName = compName
      .replace(/(?!^)([A-Z])/g, '_$1')
      .toLowerCase()
    const smallHumpCompName =
      compName[0].toLocaleLowerCase() + compName.slice(1)

    const {
      indexTemplate,
      compTemplate,
      configTemplate,
      storyTemplate,
    } = getTemplate(
      compName,
      hyphenCompName,
      underlineCompName,
      smallHumpCompName
    )

    const errFn = err => {
      if (err) {
        console.log(err)
        rejects('构建失败')
      }
    }

    const writeFileOption = { encoding: 'utf8', flag: 'a' }

    fs.mkdir(compPath, errFn)
    fs.writeFile(`${compPath}/index.tsx`, indexTemplate, writeFileOption, errFn)
    fs.writeFile(
      `${compPath}/config.tsx`,
      configTemplate,
      writeFileOption,
      errFn
    )
    // 组件逻辑文件
    fs.writeFile(
      `${compPath}/${hyphenCompName}.tsx`,
      compTemplate,
      writeFileOption,
      errFn
    )
    // 组件文档文件
    fs.writeFile(
      `${compPath}/${hyphenCompName}.stories.tsx`,
      storyTemplate,
      writeFileOption,
      errFn
    )
    // 组件测试文件
    fs.writeFile(
      `${compPath}/${hyphenCompName}.test.tsx`,
      '',
      writeFileOption,
      errFn
    )
    // 组件样式文件
    fs.writeFile(`${compPath}/_style.scss`, '', writeFileOption, errFn)

    // 样式文件全局注册
    const styleRegisterTpl = `\n@import '../components/${compName}/style';`
    fs.writeFile(
      `${stylePath}/index.scss`,
      styleRegisterTpl,
      writeFileOption,
      errFn
    )

    resolve('构建成功')
  })
}

async function main() {
  const compName = await scan('enter the new component name: ')
  let buildResult
  try {
    buildResult = await buildDir(compName)
  } catch (e) {
    buildResult = e
  }
  console.log(buildResult)
}

main()
